/*
 * @Author: lsjweiyi 759209794@qq.com
 * @Date: 2023-09-22 20:02:17
 * @LastEditors: lsjweiyi 759209794@qq.com
 * @LastEditTime: 2023-09-22 23:44:29
 * @FilePath: \ip-black\test\util.go
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
package test

import (
	"fmt"
	"math"
	"sync"
)

/**
 * @description: 创建ip，起点是[0,0,0,0],每添加一个ip，从0开始加1，如第二个ip是[1,0,0,0],而第257个ip需要进位，所以是[0,1,0,0]
 * @param {int} num 创建的ip个数
 * @param {int} chanNum 用多少个线程创建
 * @return {*}
 */
func CreateIp(num int, chanNum int) (ipList []string) {
	// 测试就不需要那么大的量把
	if num > math.MaxInt32 {
		return
	}
	ipList=make([]string, num)
	averageNum := num / chanNum //平均每个线程创建多少个

	// 保存每一个协程循环ip的起点
	chanStartIpList :=make([][4]int,chanNum) 
	// 计算每个起点的ip值，第一个起点是0，所以不需要计算，所以长度chanNum-1
	for ch := 0; ch < chanNum-1; ch++ {
		chanStartIpList[ch+1][0] = (ch+1) * averageNum // 每一段的起点就是前一段循环的终点，也就是平均值累加
		// 这里是关键，ip分为4段，每一段的最大值是255，这里就是相当于满256进一，直到每一段的值都小于256，得到的也就是一个正常的ip
		for j := 0; j < 4; j++ {
			if chanStartIpList[ch+1][j] > 255 {
				//除数进位到下一位，如第一个协程记录了1000个ip，第二个协程的开始也就是[1000,0,0,0]，但是这个ip得进位才是个正常的ip
				chanStartIpList[ch+1][j+1]+=chanStartIpList[ch+1][j]/256 
				// 而余数就是在该位置上剩余的，跟我们的加法是一个意思
				chanStartIpList[ch+1][j] = chanStartIpList[ch+1][j]%256
			}
		}
	}
	// fmt.Println(chanStartIpList)

	var wg sync.WaitGroup // 管理协程
	for ch := 0; ch < chanNum; ch++ {
		wg.Add(1)
		// 多协程创建ip，index表示第几个协程，会影响循环的起点；startIP是循环的起点ip
		go func(index int ,startIP *[4]int){
			// 每个循环都生成averageNum个ip，所以每段循环都是上一个循环加averageNum
			for i := index*averageNum; i < (index+1)*averageNum; i++ {
				ipList[i] = fmt.Sprintf("%d.%d.%d.%d", startIP[0], startIP[1], startIP[2], startIP[3])
				startIP[0]++ // 每生成一个ip，就在最左边的值里加1
				// 这里是核心，ip要进位
				for j := 0; j < 4; j++ {
					if startIP[j] > 255 {
						startIP[j] = 0 // 因为这里每加1都会进行判断，所以进位后必然为0
						startIP[j+1]++ // 因为这里每加1都会进行判断，所以每次也只可能是进一位
					}
				}
			}
			wg.Done()
		}(ch,&chanStartIpList[ch])
	}
	wg.Wait()
	return
}
